package com.lineage.server.datatables.sql;

import com.lineage.DatabaseFactory;
import com.lineage.server.datatables.CharObjidTable;
import com.lineage.server.datatables.storage.CharMapTimeStorage;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class CharMapTimeTable implements CharMapTimeStorage {
  private static final Log _log = LogFactory.getLog(CharMapTimeTable.class);
  
  private static final Map<Integer, HashMap<Integer, Integer>> _timeMap = new ConcurrentHashMap<>();
  
  public void load() {
    PerformanceTimer timer = new PerformanceTimer();
    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("SELECT * FROM `character_maps_time` ORDER BY `char_obj_id`");
      rs = ps.executeQuery();
      while (rs.next()) {
        int char_obj_id = rs.getInt("char_obj_id");
        if (CharObjidTable.get().isChar(char_obj_id) != null) {
          int order_id = rs.getInt("order_id");
          int used_time = rs.getInt("used_time");
          addTime(char_obj_id, order_id, used_time);
          continue;
        } 
        deleteTime(char_obj_id);
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
    _log.info("载入地图入场时间纪录资料数量: " + _timeMap.size() + "(" + timer.get() + "ms)");
  }
  
  public void update(int objid, int mapid, int time) {
    Connection cn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("SELECT * FROM `character_maps_time` ORDER BY `char_obj_id`");
      rs = ps.executeQuery();
      while (rs.next()) {
        int char_obj_id = rs.getInt("char_obj_id");
        if (CharObjidTable.get().isChar(char_obj_id) != null) {
          int order_id = rs.getInt("order_id");
          int used_time = rs.getInt("used_time");
          addTime(char_obj_id, order_id, used_time);
          continue;
        } 
        deleteTime(char_obj_id);
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
  
  public Map<Integer, Integer> addTime(int objId, int order_id, int used_time) {
    HashMap<Integer, Integer> list = _timeMap.get(Integer.valueOf(objId));
    if (list == null) {
      HashMap<Integer, Integer> newlist = new HashMap<>();
      newlist.put(Integer.valueOf(order_id), Integer.valueOf(used_time));
      _timeMap.put(Integer.valueOf(objId), newlist);
      return newlist;
    } 
    list.put(Integer.valueOf(order_id), Integer.valueOf(used_time));
    return list;
  }
  
  public void getTime(L1PcInstance pc) {
    HashMap<Integer, Integer> list = _timeMap.get(Integer.valueOf(pc.getId()));
    if (list != null)
      pc.setMapsList(list); 
  }
  
  public void deleteTime(int objid) {
    HashMap<Integer, Integer> list = _timeMap.get(Integer.valueOf(objid));
    if (list != null)
      list.clear(); 
    _timeMap.remove(Integer.valueOf(objid));
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("DELETE FROM `character_maps_time` WHERE `char_obj_id`=?");
      ps.setInt(1, objid);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
  
  public void saveAllTime() {
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      cn.setAutoCommit(false);
      ps = cn.prepareStatement("DELETE FROM `character_maps_time`");
      ps.execute();
      String sql = "INSERT INTO `character_maps_time`SET `char_obj_id`=?,`order_id`=?,`used_time`=?";
      Iterator<Map.Entry<Integer, HashMap<Integer, Integer>>> iterator = _timeMap.entrySet()
        .iterator();
      while (iterator.hasNext()) {
        Map.Entry<Integer, HashMap<Integer, Integer>> entryList = iterator.next();
        Iterator<Map.Entry<Integer, Integer>> iterator2 = ((HashMap<Integer, Integer>)entryList.getValue()).entrySet().iterator();
        while (iterator2.hasNext()) {
          Map.Entry<Integer, Integer> entryList2 = iterator2.next();
          Throwable t = null;
          PreparedStatement ps_each = cn.prepareStatement(
              "INSERT INTO `character_maps_time`SET `char_obj_id`=?,`order_id`=?,`used_time`=?");
          try {
            ps_each.setInt(1, ((Integer)entryList.getKey()).intValue());
            ps_each.setInt(2, ((Integer)entryList2.getKey()).intValue());
            ps_each.setInt(3, ((Integer)entryList2.getValue()).intValue());
            ps_each.execute();
          } finally {
            if (ps_each != null)
              ps_each.close(); 
          } 
        } 
      } 
      cn.commit();
      cn.setAutoCommit(true);
    } catch (SQLException e) {
      try {
        cn.rollback();
      } catch (SQLException sQLException) {}
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
  
  public void clearAllTime() {
    Iterator<HashMap<Integer, Integer>> iterator = _timeMap.values().iterator();
    while (iterator.hasNext()) {
      HashMap<Integer, Integer> list = iterator.next();
      if (list != null)
        list.clear(); 
    } 
    _timeMap.clear();
    Connection cn = null;
    PreparedStatement ps = null;
    try {
      cn = DatabaseFactory.get().getConnection();
      ps = cn.prepareStatement("DELETE FROM `character_maps_time`");
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(cn);
    } 
  }
}
